﻿package yii.db.ar{

	import yii.db.*;
	import phpas3.*;

	import yii.db.ar.*;
	import yii.db.schema.*;

	public class CJoinElement{

	/**
	 * @var integer the unique ID of this tree node
	 */
	public var id:int;
	/**
	 * @var CActiveRelation the relation represented by this tree node
	 */
	public var relation:CActiveRelation;
	/**
	 * @var CActiveRelation the master relation
	 */
	public var master:CActiveRelation;
	/**
	 * @var CActiveRelation the slave relation
	 */
	public var slave:CActiveRelation;
	/**
	 * @var CActiveRecord the model associated with this tree node
	 */
	public var model:CActiveRecord;
	/**
	 * @var array list of active records found by the queries+ They are indexed by primary key values+
	 */
	public var records:Array=new Array();
	/**
	 * @var array list of child join elements
	 */
	public var children:Array=new Array();
	/**
	 * @var array list of stat elements
	 * @since 1+0+4
	 */
	public var stats:Array=new Array();
	/**
	 * @var string table alias for this join element
	 */
	public var tableAlias:String;
	/**
	 * @var string the quoted table alias for this element
	 */
	public var rawTableAlias;

	private var _finder;
	private var _builder;
	private var _parent;
	private var _pkAlias;  				// string or name=>alias
	private var _columnAliases:Array=new Array();	// name=>alias
	private var _joined=false;
	private var _table;
	private var _related:Array=new Array();			// PK, relation name, related PK => true






	/**
	 * @return string the column prefix for column reference disambiguation
	 */
	public function getColumnPrefix():String{
		if(this.tableAlias!==null)
			return this.rawTableAlias+'+';
		else
			return this._table.rawName+'+';
	}




	/**
	 * Builds the join query with all descendant HAS_ONE and BELONGS_TO nodes+
	 * @param CJoinQuery $query the query being built up
	 */
	public function buildQuery( $query:CJoinQuery ):void{
		for( var index in this.children ){
			var $child = this.children[index];
			if($child.master!==null){
				$child._joined=true;
			} else if($child.relation is CHasOneRelation || $child.relation is CBelongsToRelation || this._finder.joinAll || $child.relation.together || (!this._finder.baseLimited && $child.relation.together===null)){
				$child._joined=true;
				$query.join($child);
				$child.buildQuery($query);
			}
		}
	}





	/**
	 * Count the number of primary records returned by the join statement+
	 * @param CDbCriteria $criteria the query criteria
	 * @return string number of primary records+ Note: type is string to keep max+ precision+
	 * @since 1+0+3
	 */
	public function count( $criteria:CDbCriteria=null ):String{
		var $query:CJoinQuery = new CJoinQuery(this,$criteria);
		// ensure only one big join statement is used
		this._finder.baseLimited=false;
		this._finder.joinAll=true;
		this.buildQuery($query);

		var $select:String = is_array($criteria.select) ? implode(',',$criteria.select) : $criteria.select;
		if( $select!=='*' && !strncasecmp($select,'count',5) ){
			$query.selects= new Array($select);
		} else if(is_string(this._table.primaryKey)){
			var $prefix:String = this.getColumnPrefix();
			var $schema = this._builder.getSchema();
			var $column = $prefix+$schema.quoteColumnName(this._table.primaryKey);
			$query.selects = new Array("COUNT(DISTINCT "+ $column +")");
		} else {
			$query.selects = new Array("COUNT(*)");
		}

		$query.orders=$query.groups=$query.havings=new Array();
		$query.limit=$query.offset=-1;
		var $command:CDbCommand = $query.createCommand(this._builder);
		return $command.queryScalar();
	}




	}
}